<template>
    <div class='player' v-show='playlist.length>0'>
        <transition name='normal'
                    @enter="enter"
                    @after-enter="afterEnter"
                    @leave="leave"
                    @after-leave="afterLeave"
        >
            <div class="normal-player" v-show='fullScreen'>
                <div class="bg-img">
                    <img :src="currentSong.image" alt="歌曲图片">
                </div>
                <div class="top">
                    <i class="icon-back" @click='back'></i>
                    <h1 class="title" v-html="currentSong.name"></h1>
                    <h2 class="subtitle" v-html="currentSong.singer"></h2>
                </div>
                <div
                        class="middle"
                        @touchstart.prevent='touchStart'
                        @touchmove.prevent='touchMove'
                        @touchend='touchEnd'
                >
                    <div class="cd-wrapper">
                        <img class='cd-img' :class="{'play':playing,'play pause':!playing,'active': currentShow === 0}"
                             :src="currentSong.image" alt="旋转歌手头像" ref='cdImg'>
                        <div class="lyric-now">
                            <span class='text' v-show='currentShow === 0'>{{currentText}}</span>
                        </div>
                    </div>
                    <scroll class='lyric-scroll' :class="{'active': currentShow === 1}" ref="lyricList"
                            v-if="currentLyric && currentLyric.lines">
                        <div class="lyric-wrapper">
                            <div v-if="currentLyric">
                                <p ref="lyricLine"
                                   class="text"
                                   :class="{'current': currentLineNum === index}"
                                   v-for="(line, index) in currentLyric.lines">{{line.txt}}</p>
                            </div>
                        </div>
                    </scroll>
                </div>
                <div class="bottom">
                    <div class="dot-wrapper">
                        <span class="dot" :class="{'active':currentShow===0}"></span>
                        <span class="dot" :class="{'active':currentShow===1}"></span>
                    </div>
                    <div class="progress-wrapper">
                        <span class='time time-l' v-text="currentFormatTime"></span>
                        <div class="progress-bar" ref='bar'>
                            <myprogress :percent='percent' @percentChange='percentChange'></myprogress>
                        </div>
                        <span class='time time-r' v-text="durationFormatTime"></span>
                    </div>
                    <div class="operators">
                        <div class="icon left-icon"><i @click='changeMode' :class="modeInfo.icon"></i></div>
                        <div class="icon left-icon"><i class="icon-prev" @click='prev'></i></div>
                        <div class="icon play-icon">
                            <i :class="{'icon-play': !playing, 'icon-pause': playing}" @click='togglePlaying'></i>
                        </div>
                        <div class="icon right-icon"><i class="icon-next" @click='next'></i></div>
                        <div class="icon right-icon">
                            <i class="icon" :class='[isLove(currentSong) ? "icon-favorite" : "icon-not-favorite"]' @click='toggleLove(currentSong)'></i>
                        </div>
                    </div>
                </div>
            </div>
        </transition>
        <transition name="mini">
            <div class="mini-player" v-show='!fullScreen' @click='open'>
                <div class="left">
                    <div class="icon">
                        <img :class="{'play':playing,'play pause':!playing}" :src="currentSong.image" alt="歌曲图片"
                             ref='miniImg'>
                    </div>
                    <div class="text">
                        <h2 class="name" v-html='currentSong.name'></h2>
                        <p class="desc" v-html='currentSong.singer'></p>
                    </div>
                </div>
                <div class="right">
                    <div class="control">
                        <myprogressc :size='32' :percent='percent'>
                            <i class='icon-mini' :class="{'icon-play-mini': !playing, 'icon-pause-mini': playing}"
                               @click.stop='togglePlaying'></i>
                        </myprogressc>
                    </div>
                    <div class="control">
                        <i class="icon-playlist" @click.stop="showList">
                        </i>
                    </div>
                </div>
            </div>
        </transition>
        <audio
                :src="currentSong.url"
                @play='ready'
                @error='error'
                @timeupdate='timeupdate'
                ref='audio'>
        </audio>
        <player-list ref="playerList"></player-list>
    </div>
</template>
<script>
    import { mapGetters, mapMutations, mapActions } from 'vuex';
    import animations from 'create-keyframe-animation';
    import Lyric from 'lyric-parser';
    import { saveHistoryPlay } from '@/common/js/cache';
    import { random, formatTime } from '@/common/js/dom';
    import { playMode } from '@/common/js/config';
    import myprogress from '@/base/progress';
    import myprogressc from '@/base/progress-circle';
    import scroll from '@/base/scroll';
    import { playerMixin } from '@/common/js/mixin';
    import playerList from '../player-list/player-list';

    const PLAYER_CTRL = {
        next: 'next',
        prev: 'prev',
    };
    const LYRIC_OFFSET = 5;
    const LIMIT_WIDTH = window.innerWidth / 5;
    export default {
        mixins: [playerMixin],
        name: 'player',
        data() {
            return {
                songReady: false,
                currentTime: 0,
                currentLyric: null,
                currentText: '',
                currentLineNum: 0,
                currentShow: 0,
            };
        },
        computed: {
            percent() {
                if (this.currentSong) {
                    return this.currentTime / this.currentSong.duration;
                }
                return 0;
            },
            currentFormatTime() {
                return formatTime(this.currentTime);
            },
            durationFormatTime() {
                return formatTime(this.currentSong.duration);
            },
            ...mapGetters([
                'fullScreen',
                'playlist',
                'playing',
                'currentIndex',
                'mode',
            ]),
        },
        watch: {
            currentSong(now) {
                if (!now.id) {
                    return;
                }
                // setTimeout
                clearTimeout(this.timer);
                this.timer = setTimeout(() => {
                    this._lyricRefresh();
                    this.dom.audio.play();
                }, 500);
            },
            playing(now) {
                clearTimeout(this.timer2);
                this.timer2 = setTimeout(() => {
                    const audio = this.dom.audio;
                    console.log(now);
                    now ? audio.play() : audio.pause();
                }, 500);
//                this.$nextTick(() => {
//                    const audio = this.dom.audio;
//                    console.log(now);
//                    now ? audio.play() : audio.pause();
//                });
            },
        },
        methods: {
            showList() {
                this.$refs.playerList.show();
            },
            back() {
                this.SET_FULL_SCREEN(false);
            },
            open() {
                this.SET_FULL_SCREEN(true);
                this.$refs.lyricList.refresh();
            },
            togglePlaying() {
                this.SET_PLAYING_STATE(!this.playing);
                this.currentLyric && this.currentLyric.togglePlay();
            },
            next() {
                this.setIndexByMode(this.mode, this.currentIndex, PLAYER_CTRL.next);
            },
            prev() {
                this.setIndexByMode(this.mode, this.currentIndex, PLAYER_CTRL.prev);
            },
            getLyric() {
                this.currentSong.getLyric().then((lyric) => {
                    if (this.currentSong.lyric !== lyric) {
                        return;
                    }
                    // 转换为lyric实例,并保存该dom对象
                    this.currentLyric = new Lyric(lyric, this.handleLyric);
                        if (this.playing) {
                            this.currentLyric.play();
                        }
                }).catch(() => {
                    this.currentLyric = null;
                    this.currentLineNum = 0;
                });
            },
            handleLyric({ lineNum, txt }) {
                this.currentLineNum = lineNum;
                this.currentText = txt;
                let lineIndex = null;
                if (lineNum > LYRIC_OFFSET) {
                    lineIndex = lineNum - LYRIC_OFFSET;
                } else {
                    lineIndex = 0;
                }
                this.$refs.lyricList && this.$refs.lyricList.scrollToElement(this.$refs.lyricLine[lineIndex], 1000);
            },
            setIndexByMode(mode, index, type) {
                // 等待资源加载完毕
                if (!this.songReady) {
                    return;
                }
                if (mode === playMode.sequence) {
                    // 顺序播放
                    if (type === PLAYER_CTRL.next) {
                        this.SET_CURRENT_INDEX(index + 1 === this.playlist.length ? 0 : index + 1);
                    }
                    if (type === PLAYER_CTRL.prev) {
                        this.SET_CURRENT_INDEX(index - 1 === -1 ? this.playlist.length - 1 : index - 1);
                    }
                }
                if (mode === playMode.loop || this.playlist.length === 1) {
                    // 循环播放 或者 只有1首
                    // 由于index并没有改变,手动重新开始
                    this.dom.audio.currentTime = 1;
                    this._lyricRefresh();
                }
                if (mode === playMode.random) {
                    this.SET_CURRENT_INDEX(random(this.playlist.length));
                }
                if (!this.playing) {
                    this.togglePlaying();
                }
                // 标志位重置
                this.songReady = false;
            },
            touchStart(e) {
                this.start.x1 = e.touches[0].pageX;
                this.start.y1 = e.touches[0].pageY;
            },
            touchMove(e) {
                // const lyricList = this.$refs.lyricList.$el;
                this.start.disX = e.touches[0].pageX - this.start.x1;
                this.start.disY = e.touches[0].pageY - this.start.y1;
                this.start.x2 = e.touches[0].pageX;
                this.start.y2 = e.touches[0].pageY;
                if (this.start.disX <= 0 && this.currentShow === 0) {
                    // 显示歌词
                    if (this.start.disY > Math.abs(this.start.disX)) {
                        // 垂直滚动
                        this.back();
                        return;
                    }
                    if (-this.start.disX >= LIMIT_WIDTH) {
                        this.currentShow = 1;
                    }
                }
                if (this.start.disX > 0 && this.currentShow === 1) {
                    // 隐藏歌词
                    if (Math.abs(this.start.disY) > Math.abs(this.start.disX) + 10) {
                        // 垂直滚动
                        return;
                    }
                    if (this.start.disX > LIMIT_WIDTH) {
                        this.currentShow = 0;
                    }
                }
            },
            touchEnd() {
                this.start = {};
            },
            ready() {
                // 资源请求成功的标志位
                this.songReady = true;
                // 记录播放历史
                this.savePlayHistory(saveHistoryPlay(this.currentSong));
            },
            error() {
                // 即使请求失败,也算准备完毕
                this.songReady = true;
            },
            timeupdate(e) {
                if (e.target.currentTime >= this.currentSong.duration) {
                    this.next();
                }
                this.currentTime = e.target.currentTime;
            },
            percentChange(percent) {
                // 子组件传递当前进度
                const audio = this.dom.audio;
                // todo
                if (isNaN(percent)) {
                    return;
                }
                audio.currentTime = percent * audio.duration;
                this.currentLyric.seek(audio.currentTime * 1000);
                if (!this.playing) {
                    this.togglePlaying();
                }
                if (percent >= 1) {
                    this.next();
                }
            },
            enter(el, done) {
                this._getPosAndScale();
                const { x, y, scale } = this.target;
                const animation = {
                    0: {
                        transform: `translate3d(${-x}px, ${y}px, 0) scale(${scale})`,
                    },
                    60: {
                        transform: 'translate3d(0, 0, 0) scale(1.2)',
                    },
                    70: {
                        transform: 'translate3d(0, 0, 0) scale(1.1)',
                    },
                    80: {
                        transform: 'translate3d(0, 0, 0) scale(1.2)',
                    },
                    90: {
                        transform: 'translate3d(0, 0, 0) scale(1.1)',
                    },
                    100: {
                        transform: 'translate3d(0, 0, 0) scale(1)',
                    },
                };
                animations.registerAnimation({
                    name: 'move',
                    animation,
                    presets: {
                        duration: 400,
                        easing: 'linear',
                    },
                });
                animations.runAnimation(this.$refs.cdImg, 'move', done);
            },
            afterEnter() {
                animations.unregisterAnimation('move');
                this.$refs.cdImg.style.animation = '';
            },
            leave(el, done) {
                // this._getPosAndScale();
                const { x, y, scale } = this.target;
                const animation = {
                    0: {
                        transform: 'translate3d(0, 0, 0) scale(1)',
                    },
                    100: {
                        transform: `translate3d(${-x}px,${y}px,0) scale(${scale})`,
                    },
                };
                animations.registerAnimation({
                    name: 'move',
                    animation,
                    presets: {
                        duration: 400,
                        easing: 'linear',
                    },
                });
                animations.runAnimation(this.$refs.cdImg, 'move', done);
                // todo
                // this.$refs.cdImg.style.transition = 'all 0.4s';
                // this.$refs.cdImg.style.transform = `translate3d(${x}px,${y}px,0) scale(${scale})`;
                // setTimeout(done, 400);
                // this.$refs.cdImg.addEventListener('transitionend', done, false);
            },
            afterLeave() {
                // 清空 过渡动画
                animations.unregisterAnimation('move');
                this.$refs.cdImg.style.animation = '';
                // todo
                // this.$refs.cdImg.style.transition = '';
                // this.$refs.cdImg.style.transform = '';
            },
            _lyricRefresh() {
                if (this.currentLyric) {
                    // this.currentLyric.seek(0);
                    this.currentLineNum = 0;
                    this.currentLyric.stop();
                    this.currentLyric = null;
                }
                this.getLyric();
            },
            // 获取相关偏移量
            _getPosAndScale() {
                const miniImg = this.$refs.miniImg;
                const cdImg = this.$refs.cdImg;
                const scale = miniImg.offsetWidth / cdImg.offsetWidth;
                const x = cdImg.offsetLeft + (cdImg.offsetWidth / 2) - miniImg.offsetLeft - (miniImg.offsetWidth / 2);
                const y = window.innerHeight - cdImg.offsetTop - (cdImg.offsetWidth / 2) - (miniImg.offsetWidth / 2) - 10;
                this.target = {
                    x,
                    y,
                    scale,
                };
            },
            ...mapMutations([
                'SET_FULL_SCREEN',
                'SET_PLAYING_STATE',
                'SET_CURRENT_INDEX',
            ]),
            ...mapActions([
                'savePlayHistory',
            ]),
        },
        components: {
            myprogress,
            myprogressc,
            scroll,
            playerList,
        },
        created() {
            this.start = {};
        },
        mounted() {
            this.dom = {};
            this.dom.audio = this.$refs.audio;
        },
    };
</script>
<style lang='stylus' scoped>
    @import "~styl/var"
    @import '~styl/mixin'

    .player
        .normal-player
            position fixed
            top 0
            left 0
            right 0
            bottom 0
            z-index $highest
            background $color-background
            .bg-img
                position absolute
                left 0
                top 0
                width 100%
                height 100%
                z-index $low
                opacity 0.6
                filter: blur(20px)
                img
                    width 100%
                    height 100%
            .top
                position relative
                margin-bottom 25px
                text-align center
                .icon-back
                    display: block
                    padding: 9px
                    font-size: $font-size-large-x
                    color: $color-theme
                    transform: rotate(-90deg)
                    position absolute
                    top 0
                    left 6px
                    z-index $high
                .title
                    ellipsis()
                    line-height 40px
                    font-size $font-size-large
                .subtitle
                    line-height 20px
                    font-size $font-size-medium
            .middle
                position fixed
                top 80px
                bottom 170px
                width 100%
                font-size 0
                white-space nowrap
                .cd-wrapper
                    display inline-block
                    vertical-align top
                    position relative
                    height 0
                    width 100%
                    padding-top 80%
                    .lyric-now
                        width 80%
                        margin 30px auto 0
                        text-align center
                        white-space nowrap
                        overflow hidden
                        .text
                            height: 20px
                            line-height: 20px
                            font-size: $font-size-medium
                            color: $color-text-l
                    .cd-img
                        display inline-block
                        box-sizing border-box
                        position absolute
                        left 10%
                        top 0
                        width 80%
                        border 10px solid rgba(255, 255, 255, .1)
                        border-radius 50%
                        transition opacity .4s
                        opacity 0
                        &.play
                            animation rotate 20s linear infinite
                        &.pause
                            animation-play-state paused
                        &.active
                            opacity 1
                .lyric-scroll
                    vertical-align top
                    display inline-block
                    width 100%
                    overflow hidden
                    transition transform .4s
                    transform translate3d(0, 0, 0)
                    &.active
                        transform translate3d(-100%, 0, 0)
                    .lyric-wrapper
                        width: 80%
                        margin: 0 auto
                        overflow: hidden
                        text-align: center
                        .text
                            line-height: 32px
                            color: $color-text-l
                            font-size: $font-size-medium
                            &.current
                                color: $color-text
            .bottom
                position absolute
                bottom 50px
                left 0
                width 100%
                font-size 0
                .dot-wrapper
                    font-size 0
                    text-align center
                    .dot
                        display: inline-block
                        vertical-align: middle
                        margin: 0 4px
                        width: 8px
                        height: 8px
                        border-radius: 50%
                        background: $color-text-l
                        transition width .4s
                        &.active
                            width: 20px
                            border-radius: 5px
                            background: $color-text-ll
                .operators
                    display flex
                    justify-content space-around
                    align-items center
                    .icon
                        flex 1
                        color: $color-theme
                        line-height 26px
                        &.left-icon
                            font-size 30px
                            text-align right
                        &.play-icon
                            font-size 40px
                            padding 0 20px
                            text-align center
                        &.right-icon
                            font-size 30px
                            text-align left
                .progress-wrapper
                    display flex
                    width 80%
                    padding 10px 0
                    margin 0 auto
                    .progress-bar
                        flex 1
                        position relative
                        padding 13px 0
                    .time
                        color $color-text
                        font-size $font-size-small
                        flex 0 0 30px
                        line-height 30px
                        width 30px
                    .time-l
                        text-align left
                    .time-r
                        text-align right
            &.normal-enter-active, &.normal-leave-active
                transition all 0.4s
                .top, .bottom
                    transition all 0.4s cubic-bezier(0.86, 0.18, 0.82, 1.32)
            &.normal-enter, &.normal-leave-to
                opacity 0
                .top
                    transform translate3d(0, -100px, 0)
                .bottom
                    transform translate3d(0, 100px, 0)
        .mini-player
            position fixed
            z-index $higher
            display flex
            align-items center
            justify-content space-between
            bottom 0
            left 0
            width 100%
            background $color-highlight-background
            height 60px
            &.mini-enter-active, &.mini-leave-active
                transition all 0.4s
            &.mini-enter, &.mini-leave-to
                opacity 0
            .left
                display flex
                .icon
                    width 40px
                    padding 0 10px 0 20px
                    img
                        width 40px
                        height 40px
                        border-radius 50%
                        &.play
                            animation rotate 20s linear infinite
                        &.pause
                            animation-play-state paused
                .text
                    flex 1
                    line-height 20px
                    .name
                        margin-bottom 2px
                        no-wrap()
                        font-size $font-size-medium
                        color $color-text
                    .desc
                        no-wrap()
                        font-size $font-size-small
                        color $color-text-d
            .right
                display flex
                .control
                    width 30px
                    padding 0 10px
                    i
                        font-size 30px
                        color $color-theme-d
                        &.icon-mini
                            font-size 32px
                            position absolute
                            left 0
                            top 0

    @keyframes rotate
        0%
            transform: rotate(0)
        100%
            transform: rotate(360deg)
</style>
